package cn.maihe.elg.operation.centers.hymake.handler.service;

import cn.maihe.elg.operation.centers.hymake.config.HyMakeInfoConfig;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.xm.XMBaseRespDTO;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.xm.XMClaimApplyReqDTO;
import cn.maihe.elg.operation.centers.hymake.enums.HyMakeCheckResultEnum;
import cn.maihe.elg.operation.centers.hymake.enums.HyMakeRespCodeEnum;
import cn.maihe.elg.operation.centers.hymake.exception.HyMakeException;
import cn.maihe.elg.operation.centers.hymake.handler.HyMakeCenterTradeService;
import cn.maihe.elg.operation.centers.supports.CenterTradeContext;
import cn.maihe.elg.operation.centers.supports.annotation.CenterTradeService;
import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.model.enums.CenterProviderEnum;
import cn.maihe.elg.operation.model.enums.ClaimsStatus;
import cn.maihe.elg.operation.model.enums.RefundOrderStatus;
import cn.maihe.elg.operation.model.enums.TradeType;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDOCondition;
import cn.maihe.elg.operation.repository.entity.BidCustomerDO;
import cn.maihe.elg.operation.repository.entity.BidCustomerDOCondition;
import cn.maihe.elg.operation.repository.entity.GuaranteeInstitutionDO;
import cn.maihe.elg.operation.repository.entity.ProjectInfoDO;
import cn.maihe.elg.operation.repository.entity.RefundOrderInfoDO;
import cn.maihe.elg.operation.service.business.BidCustomerService;
import cn.maihe.elg.operation.service.business.InstitutionService;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.RefundOrderInfoService;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.elg.operation.utils.LogPrintUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Instant;
import java.util.Date;
import java.util.Map;

/**
 * @Description 保函理赔申请
 * @Author caixh
 * @Date 2022/3/30.
 * <p>
 * 3.1.11、接收受益人索赔申请(文件)
 */
@CenterTradeService(
        provider = CenterProviderEnum.XIANMEN,
        centerNo = CenterNoEnum.XIAMEN,
        tradeType = TradeType.lstClaim,
        reqClass = XMClaimApplyReqDTO.class,
        respClass = XMBaseRespDTO.class
)
@Slf4j
public class XMClaimApplyService extends HyMakeCenterTradeService<XMClaimApplyReqDTO, XMBaseRespDTO> {

    @Resource
    AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    RefundOrderInfoService refundOrderInfoService;
    @Resource
    ProjectInfoService projectInfoService;
    @Resource
    InstitutionService institutionService;

    @Resource
    BidCustomerService bidCustomerService;

    public XMClaimApplyService(HyMakeInfoConfig centerInfosConfig) {
        super(centerInfosConfig);
    }


    /**
     * 具体业务处理
     *
     * @param context
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public XMBaseRespDTO processService(CenterTradeContext<XMClaimApplyReqDTO, XMBaseRespDTO> context) {
        XMClaimApplyReqDTO req = context.getReq();
        Long orgId = context.getOrgId();
        String appId = req.getAppid();

        XMClaimApplyReqDTO.ClaimInfo claimInfo = req.getClaimInfo();
        String bidderName = claimInfo.getBidderName();
        String bidderCreditCode = claimInfo.getBidderCreditCode();

        BidCustomerDO bidCustomerDO = bidCustomerService.selectOne(BidCustomerDOCondition.builder()
                //.andFollowIdEq(appId)
                .andBidderNameEq(bidderName).andBidderCreditCodeEq(bidderCreditCode).build());
        if (bidCustomerDO == null) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("投标人信息不存在")
                    .build();
        }

        AcceptOrderInfoDO orderInfo = acceptOrderInfoService.selectOne(AcceptOrderInfoDOCondition.builder()
                .andGuaranteeNoEq(claimInfo.getPolicyNo()).andBidCustomerIdEq(bidCustomerDO.getId()).andOrgIdEq(orgId).build());
//        AcceptOrderInfoDO orderInfo = acceptOrderInfoService.selectOne(AcceptOrderInfoDOCondition.builder()
//                .andBidCustomerIdEq(bidCustomerDO.getId()).andOrgIdEq(orgId).build());
        if (orderInfo == null) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("查无此投保申请记录")
                    .build();
        }

        if (orderInfo.getStatus() == AcceptOrderStatus.FINISH.getStatus()) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("保函已完成，不能理赔申请")
                    .build();
        }
        if (orderInfo.getStatus() == AcceptOrderStatus.CANCEL.getStatus()) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("保函已取消，不能理赔申请")
                    .build();
        }
        if (orderInfo.getStatus() != AcceptOrderStatus.HAS_OUT_GUARANTEE.getStatus()) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("已出函状态才能发起理赔")
                    .build();
        }

        ClaimsStatus claimsStatus = ClaimsStatus.resolve(orderInfo.getClaimsStatus());
        if (claimsStatus == ClaimsStatus.SUCCESS) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("理赔处理完成[" + claimsStatus + "]," + orderInfo.getClaimsRemark())
                    .build();
        }
        if (claimsStatus == ClaimsStatus.PROCESSING) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("理赔处理中,不能重复发起理赔")
                    .build();
        }

        ProjectInfoDO projectInfoDO = projectInfoService.selectById(orderInfo.getProjectId());
        GuaranteeInstitutionDO institutionDO = institutionService.selectById(orderInfo.getInstitutionId());

        AcceptOrderInfoDO updateOrderInfo = AcceptOrderInfoDO.builder()
                .id(orderInfo.getId())
                .claimsStatus(ClaimsStatus.PROCESSING.getStatus())
                .claimsRemark(claimInfo.getReason()).build();
        acceptOrderInfoService.updateById(updateOrderInfo);

        String revokeNo = orderInfo.getGuaranteeNo();
        RefundOrderInfoDO curDo = refundOrderInfoService.getByGuaranteeNo(revokeNo);
        if (curDo != null && (curDo.getRefundOrderNo().equals(req.getClaimId())
                || claimsStatus == ClaimsStatus.FAILURE
                || claimsStatus == ClaimsStatus.NO_PASSED)) {
            curDo.setRemark(claimInfo.getReason());
            curDo.setApplyUserName(projectInfoDO.getTendererContact());
            curDo.setApplyUserPhone(projectInfoDO.getTendererContactTel());
            curDo.setStatus(RefundOrderStatus.UNREFUND.getStatus());
            refundOrderInfoService.updateById(curDo);
        } else {
            //配合后管进行 审核操作，审核操作中需要同步到 accepInfo中的理赔最终状态
            curDo = RefundOrderInfoDO.builder()
                    .id(IdGenerate.getId()).centerId(context.getCenterId())
                    .orgId(context.getOrgId())
                    .guaranteeNo(orderInfo.getGuaranteeNo())
                    .centerOrderId(orderInfo.getCenterOrderId())
                    .acceptOrderNo(orderInfo.getAcceptOrderNo())
                    .applyOrderNo(orderInfo.getApplyOrderNo())
                    .guaranteeType(orderInfo.getGuaranteeType())
                    .guaranteeCategory(orderInfo.getGuaranteeCategory())
                    .guaranteeFee(orderInfo.getGuaranteeFee())
                    .projectId(orderInfo.getProjectId())
                    .projectName(projectInfoDO.getProjectName())
                    .sectionName(orderInfo.getSectionName())
                    .bidCustomerId(orderInfo.getBidCustomerId())
                    .bidCustomerName(orderInfo.getBidCustomerName())
                    .bidIndate(orderInfo.getBidIndate())
                    .bidBond(projectInfoDO.getBidBond())
                    .institutionId(orderInfo.getInstitutionId())
                    .institutionName(institutionDO.getGuarantorName())
                    .attachmentId(orderInfo.getAttachmentId()).remark(claimInfo.getReason())
                    .inviteCode(orderInfo.getInviteCode())
                    .refundOrderNo(req.getClaimId())
                    // todo 参数：不确定理赔人姓名，电话。
//                    .applyUserName(req.getClaimName())
//                    .applyUserPhone(req.getClaimPhone())
                    .gmtCreate(Date.from(Instant.now())).gmtModified(Date.from(Instant.now()))
                    .userCreate("接口申请")
                    .status(RefundOrderStatus.UNREFUND.getStatus())
                    .build();
            refundOrderInfoService.insert(curDo);
        }


        return XMBaseRespDTO.builder()
                .success(true)
                .build();
    }

    @Override
    protected XMClaimApplyReqDTO buildReq(Map<String, Object> clearParams) {
        try {
            ElgLogger.debug(log, l -> l.debug("保函理赔申请 请求原文：{}", LogPrintUtil.toJsonString(clearParams)));
            String jsonString = JSONObject.toJSONString(clearParams);
            ElgLogger.debug(log, l -> l.debug("保函理赔申请 请求jsonString：{}", LogPrintUtil.toJsonString(jsonString)));
            String clearString = jsonString.replace("\\\"", "\"")
                    .replace("\\\\\"", "\"")
                    .replace("\"[", "[")
                    .replace("]\"", "]")
                    .replace("\"{", "{")
                    .replace("}\"", "}");
            ElgLogger.debug(log, l -> l.debug("保函理赔申请 请求clearString：{}", LogPrintUtil.toJsonString(clearString)));
            return JSONObject.parseObject(clearString, this.reqClass);
        } catch (Exception e) {
            throw HyMakeException.of(HyMakeRespCodeEnum.FAILURE, "反序列化异常", e);
        }
    }
}
